package com.dubbo;

import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.StringUtils;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class b {
    private static final String DEFAULT_CHARSET = AlipayConstants.CHARSET_UTF8;
    private static int keepAliveTimeout = 15000;
    public static void main(String[] args) {
//        try {
////            HttpURLConnection conn =getConn();
////            String rsp = getResponseAsString(conn);
////            System.out.println(rsp);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

//    private static HttpURLConnection getConn() {
//        HttpURLConnection conn = null;
//        try {
//            String charset="UTF-8";
//            String ctype = "application/x-www-form-urlencoded;charset=" + charset;
//            Map<String, String> params=new HashMap<String, String>();
//            params.put("appid", "1");
//            params.put("secret", "2");
//            params.put("code", "3");
//            params.put("grant_type", "authorization_code");
//            String query = buildQuery(params, charset);
//            URL url=buildGetUrl("https://api.weixin.qq.com/sns/oauth2/access_token", query);
//
////            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
//            Proxy proxy = null;
//            if ("https".equals(url.getProtocol())) {
//                HttpsURLConnection connHttps = null;
//                if (proxy != null) {
//                    connHttps = (HttpsURLConnection) url.openConnection(proxy);
//                } else {
//                    connHttps = (HttpsURLConnection) url.openConnection();
//                }
////                if (!needCheckServerTrusted) {
////                    //设置不校验服务端证书的SSLContext
////                    connHttps.setSSLSocketFactory(socketFactory);
////                    connHttps.setHostnameVerifier(verifier);
////                }
//                conn = connHttps;
//            } else {
//                if (proxy != null) {
//                    conn = (HttpURLConnection) url.openConnection(proxy);
//                } else {
//                    conn = (HttpURLConnection) url.openConnection();
//                }
//            }
//            conn.setRequestMethod("GET");
//            conn.setDoInput(true);
//            conn.setDoOutput(true);
//            conn.setRequestProperty("Accept", "text/plain,text/xml,text/javascript,text/html");
////            conn.setRequestProperty("User-Agent", "aop-sdk-java");
//            conn.setRequestProperty("Content-Type", ctype);
////            if (headers != null) {
////                for (Map.Entry<String, String> header : headers.entrySet()) {
////                    conn.setRequestProperty(header.getKey(), header.getValue());
////                }
////            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }finally {
//            if (conn != null) {
//                conn.disconnect();
//            }
//        }
//    }

    protected static String getResponseAsString(HttpURLConnection conn) throws IOException {
        String charset = "UTF-8";

        //此时设置KeepAlive超时所需数据结构才刚初始化完整，可以通过反射修改
        //同时也不宜将修改时机再滞后，因为可能后续连接缓存类已经消费了默认的KeepAliveTimeout值，再修改已经无效
//        setKeepAliveTimeout(conn);

        InputStream es = conn.getErrorStream();
        if (es == null) {
            return getStreamAsString(conn.getInputStream(), charset);
        } else {
            String msg = getStreamAsString(es, charset);
            if (StringUtils.isEmpty(msg)) {
                throw new IOException(conn.getResponseCode() + ":" + conn.getResponseMessage());
            } else {
                throw new IOException(msg);
            }
        }
    }
    private static String getStreamAsString(InputStream stream, String charset) throws IOException {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream, charset));
            StringWriter writer = new StringWriter();

            char[] chars = new char[256];
            int count = 0;
            while ((count = reader.read(chars)) > 0) {
                writer.write(chars, 0, count);
            }

            return writer.toString();
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }
    private static void setKeepAliveTimeout(HttpURLConnection connection) {
        if (keepAliveTimeout == 0) {
            return;
        }
        try {

            Field delegateHttpsUrlConnectionField = Class.forName("sun.net.www.protocol.https.HttpsURLConnectionImpl").getDeclaredField(
                    "delegate");
            delegateHttpsUrlConnectionField.setAccessible(true);
            Object delegateHttpsUrlConnection = delegateHttpsUrlConnectionField.get(connection);

            Field httpClientField = Class.forName("sun.net.www.protocol.http.HttpURLConnection").getDeclaredField("http");
            httpClientField.setAccessible(true);
            Object httpClient = httpClientField.get(delegateHttpsUrlConnection);

            Field keepAliveTimeoutField = Class.forName("sun.net.www.http.HttpClient").getDeclaredField("keepAliveTimeout");
            keepAliveTimeoutField.setAccessible(true);
            keepAliveTimeoutField.setInt(httpClient, keepAliveTimeout);
        } catch (Throwable ignored) {
            //设置KeepAlive超时只是一种优化辅助手段，设置失败不应阻塞主链路，设置失败不应影响功能
        }
    }

    public static String buildQuery(Map<String, String> params, String charset) throws IOException {
        if (params == null || params.isEmpty()) {
            return null;
        }

        StringBuilder query = new StringBuilder();
        Set<Map.Entry<String, String>> entries = params.entrySet();
        boolean hasParam = false;

        for (Map.Entry<String, String> entry : entries) {
            String name = entry.getKey();
            String value = entry.getValue();
            // 忽略参数名或参数值为空的参数
            if (StringUtils.areNotEmpty(name, value)) {
                if (hasParam) {
                    query.append("&");
                } else {
                    hasParam = true;
                }

                query.append(name).append("=").append(URLEncoder.encode(value, charset));
            }
        }

        return query.toString();
    }
    private static URL buildGetUrl(String strUrl, String query) throws IOException {
        URL url = new URL(strUrl);
        if (StringUtils.isEmpty(query)) {
            return url;
        }

        if (StringUtils.isEmpty(url.getQuery())) {
            if (strUrl.endsWith("?")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "?" + query;
            }
        } else {
            if (strUrl.endsWith("&")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "&" + query;
            }
        }

        return new URL(strUrl);
    }
}
